package com.apache.ius.plugin;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import com.apache.database.model.MethodParam;
import com.apache.ius.IusSqlTools;
import com.apache.rpc.entity.RpcDatasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.apache.api.manager.ProxyManager;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.cache.service.impl.LoadCacheFactory;
import com.apache.database.constant.SpringContextLoader;
import com.apache.database.datasource.ConnctionData;
import com.apache.database.datasource.DynamicDataSource;
import com.apache.database.db.IDao;
import com.apache.exception.BusinessException;
import com.apache.ius.able.ScheduledExecutor;
import com.apache.ius.able.SelectDatasourceCall;
import com.apache.rpc.common.LoadRpcService;
import com.apache.rpc.entity.InterfaceRegister;
import com.apache.tools.ConfigUtil;
import com.apache.tools.DataMap;
import com.apache.tools.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 插件常用方法工具类
 */
public class UtilPlugin {
	private Logger log = LoggerFactory.getLogger(getClass());
	ProxyManager iusProxyManager = (ProxyManager) SpringContextLoader.getBean("iusProxyManager");
	private IDao iusPubDao = (IDao) SpringContextLoader.getBean("iusPubDao");
	private static UtilPlugin instance;

	public static UtilPlugin getInstance() {
		if (null == instance) {
			instance = new UtilPlugin();
		}
		return instance;
	}

	/**
	 * 利用平台查询业务表数据，不带事务（具体返回单条还是多条，以whereMap中拼装的查询条件为准）
	 * @param datasource 指定系统所属数据源
	 * @param searchObjName 指定要查询的表对象，如s_teUserTest
	 * @param whereMap 拼装查询条件[格式如：对象.w_属性=值/对象.wl_属性=值]，如whereMap.put("teUserTest.w_userSex","F");
	 * @return
	 */
	public List<DataMap> getListByParams(String datasource, String searchObjName, Map<String, Object> whereMap)
			throws BusinessException {
		List<DataMap> list = new ArrayList<DataMap>();
		ParamsVo vo = new ParamsVo();
		if (whereMap != null && whereMap.size() > 0) {
			vo.setParams(whereMap);
		}

		vo.setKey("iusTransaction");
		vo.setParams("resultType", "objInfo");
		vo.setParams("resultObjType", "list");
		vo.setParams("sqlKeyId", "");
		//拼装参数
		vo.setParams("modelTypes", searchObjName);
		vo.setParams("datasource", datasource);

		log.info("请求参数：" + vo.getParams());
		//        DynamicDataSourceHolder.putDataSource(sysName);//指定数据源
		ResultEntity res = (ResultEntity) iusProxyManager.doInvoke(vo);
		if (res.getEntity() != null) {
			list = (List<DataMap>) res.getEntity();
		}
		return list;
	}


	/**
	 * 获取给定sql的数据信息
	 * @param sql 待执行sql
	 * @param pageIndex 当前页（查分页时用，不分页为0）
	 * @param pageSize 记录数（查分页时用，不分页为0）
	 * @return List<DataMap>
	 */
	public Object selectBySql(String sql, int pageIndex, int pageSize) {
		log.info("执行自定义SQL：" + sql);
		log.info("分页查询参数：pageIndex="+pageIndex+",pageSize="+pageSize);
		MethodParam params = new MethodParam("ByObjInfo", "", "", IusSqlTools.SPANCENAME);
		params.setParams("dyncSql", sql);
		params.setResultCache(false);
		if (pageSize > 0 && pageIndex > 0) {
			params.setPageIndex(pageIndex);
			params.setPageSize(pageSize);
			return iusPubDao.pageSelect(params);
		}
		return iusPubDao.select(params);
	}

	/**
	 * 利用平台处理业务表数据（提交，修改，删除），带事务
	 * @param datasource 指定系统所属数据源
	 * @param saveObjName 指定要处理的表对象，如i_teUserTest/u_teUserTest/d_teUserTest
	 * @param paramsMap 相应操作的参数、操作的条件，不能为空;
	 * @return
	 */
	public ResultEntity saveByParams(String datasource, String saveObjName, Map<String, Object> paramsMap)
			throws BusinessException {
		ParamsVo vo = new ParamsVo();
		if (paramsMap != null && paramsMap.size() > 0) {
			vo.setParams(paramsMap);
		}

		vo.setKey("iusTransaction");
		vo.setParams("resultType", "processSql");
		vo.setParams("sqlKeyId", "");
		//		vo.setParams("beforMethodKey", "");///需要调用的插件（如DoTaskPluginImpl）
		//拼装参数
		vo.setParams("modelTypes", saveObjName);
		vo.setParams("datasource", datasource);

		log.info("请求参数：" + vo.getParams());
		//        DynamicDataSourceHolder.putDataSource(sysName);//指定数据源
		ResultEntity res = (ResultEntity) iusProxyManager.saveInvoke(vo);
		return res;
	}

	/**
	 * 利用平台查询业务表数据条数，不带事务（具体返回单条还是多条，以whereMap中拼装的查询条件为准）
	 * @param datasource 指定系统所属数据源
	 * @param searchObjName 指定要查询的表对象，如s_teUserTest
	 * @param whereMap 拼装查询条件[格式如：对象.w_属性=值/对象.wl_属性=值]，如whereMap.put("teUserTest.w_userSex","F");
	 * @return
	 */
	public long countByParams(String datasource, String searchObjName, Map<String, Object> whereMap)
			throws BusinessException {
		ParamsVo vo = new ParamsVo();
		if (whereMap != null && whereMap.size() > 0) {
			vo.setParams(whereMap);
		}

		vo.setKey("iusTransaction");
		vo.setParams("resultType", "objInfo");
		vo.setParams("resultObjType", "count");
		vo.setParams("sqlKeyId", "");
		//拼装参数
		vo.setParams("modelTypes", searchObjName);
		vo.setParams("datasource", datasource);

		log.info("请求参数：" + vo.getParams());
		//        DynamicDataSourceHolder.putDataSource(sysName);//指定数据源
		ResultEntity res = (ResultEntity) iusProxyManager.doInvoke(vo);
		if (res.getEntity() != null) {
			return Long.parseLong(String.valueOf(res.getEntity()));
		}
		return 0;
	}

	/**
	 * 跨数据源RPC操作，查询业务表数据信息
	 * @param datasource 指定系统所属数据源，如平台的plateform
	 * @param modelTypes 指定要查询的表对象，如s_uctUser
	 * @param resultObjType 返回值类型 list/count
	 * @param whereMap 拼装查询条件[格式如：对象.w_属性=值/对象.wl_属性=值]，如whereMap.put("uctUser.w_userSex","F");
	 * @return
	 */
	public ResultEntity selectInfoForDatasource(String datasource, String modelTypes, String resultObjType,
			Map<String, Object> whereMap) {
		whereMap.put("datasource", datasource);
		whereMap.put("modelTypes", modelTypes);
		whereMap.put("resultObjType", resultObjType);
		whereMap.put("resultType", "objInfo");
		if (null == whereMap.get("sqlKeyId")) {
			whereMap.put("sqlKeyId", "sqlKeyId");
		}
		whereMap.put("sysPass", ConfigUtil.getInstance().interfacePass());
		log.info("请求参数：" + whereMap);
		InterfaceRegister register = new InterfaceRegister();
		register.setAddress("127.0.0.1");
		register.setCallType("socket");
		return LoadRpcService.service().doServiceClient(getBeanId(datasource), "dymicSql", whereMap, register);
	}

	/**
	 * 跨数据源RPC操作，利用平台处理业务表数据（提交，修改，删除），带事务
	 * @param datasource 指定系统所属数据源，如平台的plateform
	 * @param saveObjName 指定要处理的表对象，如i_uctUser/u_uctUser/d_uctUser
	 * @param paramsMap 相应操作的参数、操作的条件，不能为空;
	 * @return
	 */
	public ResultEntity saveInfoForDatasource(String datasource, String saveObjName, Map<String, Object> paramsMap)
			throws BusinessException {
		paramsMap.put("datasource", datasource);
		paramsMap.put("modelTypes", saveObjName);
		paramsMap.put("resultType", "processSql");
		paramsMap.put("sqlKeyId", "");
		paramsMap.put("sysPass", ConfigUtil.getInstance().interfacePass());
		log.info("请求参数：" + paramsMap);
		InterfaceRegister register = new InterfaceRegister();
		register.setAddress("127.0.0.1");
		register.setCallType("socket");
		return LoadRpcService.service().doServiceClient(getBeanId(datasource), "dymicSql", paramsMap, register);
	}

	/**
	 * 跨数据源查询
	 * @param sql 需要执行查询的sql
	 * @param datasource 指定系统所属数据源，如平台的plateform
	 */
	public Object selectObjectForDatasource(String sql, String datasource) {
		log.info("跨数据源[" + datasource + "]执行自定义SQL：" + sql);
		SelectDatasourceCall call = new SelectDatasourceCall(sql, datasource);
		try {
			Future<Object> future1 = ScheduledExecutor.instance().submitObj(call);
			Object obj = future1.get();
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 按给定的sql保存、修改或删除数信息
	 * @param datasource 指定的数据源
	 * @param sql 待执行sql
	 * @return
	 */
	public boolean saveOrUpdateBySql(String datasource, String sql) {
		DruidDataSource dbDao = null;
		if (!DynamicDataSource.getInstance().checkDataSource(datasource)) {
			Object obj = LoadCacheFactory.getInstance().getCacheManager("")
					.getCacheObjectByKey("rpc_datasource_" + datasource);
			if (null == obj) {
				return false;
			}
			RpcDatasource rds = (RpcDatasource) obj;
			if (!DynamicDataSource.getInstance().addDataSource(rds.getSysEname(), rds.getDriverClassName(),
					rds.getJdbcUrl(), rds.getJdbcUsername(), rds.getJdbcPassword())) {
				return false;
			}
		}
		log.info("通过数据源[" + datasource + "]执行自定义SQL：" + sql);
		dbDao = DynamicDataSource.getInstance().getDataSource(datasource);
		Connection con = null;
		try {
			con = dbDao.getConnection();
		} catch (SQLException e) {
			DynamicDataSource.getInstance().removeDataSource(datasource);
			return false;
		}
		return ConnctionData.getInstance().execute(con, sql);
	}

	/**
	 * 获取给定sql的数据信息
	 * @param sql 待执行sql
	 * @param datasource 指定的数据源
	 * @param pageIndex 当前页（查分页时用，不分页为0）
	 * @param pageSize 记录数（查分页时用，不分页为0）
	 * @return List<DataMap>
	 */
	public Object selectObjectForSqlByPage(String sql, String datasource, int pageIndex, int pageSize) {
		log.info("通过数据源[" + datasource + "]执行自定义SQL：" + sql);
		log.info("分页查询参数：pageIndex="+pageIndex+",pageSize="+pageSize);
		SelectDatasourceCall call = new SelectDatasourceCall(sql, datasource, pageIndex, pageSize);
		try {
			Future<Object> future1 = ScheduledExecutor.instance().submitObj(call);
			Object obj = future1.get();
			return obj;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private boolean isExites(String beanId) {
		if (StrUtil.isNull(beanId))
			return false;
		String cacheKey = "interfaceRegister_" + beanId;
		return LoadCacheFactory.getInstance().getCacheManager("").checkCacheObject(cacheKey);
	}

	private String getBeanId(String datasourceName) {
		String beanId = "iusService";
		if (StrUtil.isNotNull(datasourceName)) {
			if ("cms".equals(datasourceName)) {
				beanId = "websiteService";
			} else {
				beanId = datasourceName + "Service";
				if (!isExites(beanId) || "memberService".equals(beanId)) {
					beanId = "iusService";
				}
			}
		}
		return beanId;
	}
}
